Cloud Functions実行環境について学ぶためにOSコマンドを色々実行してみた
MAD事業部@大阪の岩田です。
本エントリは クラスメソッド Google Cloud Advent Calendar 2021 の 2日目 の記事です。
個人的にマネージドサービスの裏側を想像するのが好きなので、FaaS実行環境でOSコマンドを実行して出力を見ながらニヤニヤするアレをやってみました。
やってみる
ということで早速やっていきます。
- トリガーはHTTP
- ランタイムはNode.js14
を指定して以下のソースコードを準備します。
const execSync = require('child_process').execSync; exports.helloWorld = (req, res) => { const cmd = 'ここに実行したいOSコマンドを設定' const result = execSync(cmd).toString(); res.status(200).send(result); };
あとは変数cmd
の中身に実行したいOSコマンドを設定して実行、出力を確認していきます。実行したいコマンドをクエリストリングで渡そうかとも思ったのですが、検証とはいえOSコマンドインジェクションバリバリな実装をするのはどうかと思い留まりました。
実行するOSコマンドについては既に先人がパスの通っているコマンド一覧を調査されていたので、こちらを参考にさせて頂きました。
では諸々のコマンドの実行結果を見ていきましょう。
pwd
/workspace
/workspaceなんてディレクトがあるんですね
ls -al /
total 0 drwxr-xr-x 2 root root 0 Nov 30 13:55 . drwxr-xr-x 2 root root 0 Nov 30 13:55 .. drwxr-xr-x 2 root root 0 Oct 21 03:26 bin drwxr-xr-x 2 root root 0 Jan 1 2000 boot dr-xr-xr-x 2 www-data www-data 0 Nov 30 13:56 cloudsql drwxr-xr-x 2 root root 0 Jan 1 1980 cnb dr-xr-xr-x 1 root root 0 Nov 30 13:56 dev drwxr-xr-x 2 root root 0 Nov 25 05:26 etc lrwxrwxrwx 1 root root 0 Oct 21 03:28 home -> /tmp drwxr-xr-x 2 www-data www-data 0 Jan 1 1980 layers drwxr-xr-x 2 root root 0 Oct 21 03:27 lib drwxr-xr-x 2 root root 0 Jan 1 2000 lib64 drwxr-xr-x 2 root root 0 Jan 1 2000 media drwxr-xr-x 2 root root 0 Jan 1 2000 mnt drwxr-xr-x 2 root root 0 Jan 1 2000 opt dr-xr-xr-x 2 root root 0 Nov 30 13:56 proc lrwxrwxrwx 1 root root 0 Oct 21 03:28 root -> /tmp lrwxrwxrwx 1 root root 0 Oct 21 03:28 run -> /tmp/run drwxr-xr-x 2 root root 0 Oct 21 03:26 sbin lrwxrwxrwx 1 root root 0 Oct 21 03:28 serve -> /usr/bin/serve lrwxrwxrwx 1 root root 0 Nov 10 05:57 srv -> /workspace drwxr-xr-x 2 root root 0 Nov 10 05:54 staging lrwxrwxrwx 1 root root 0 Oct 21 03:28 start -> /usr/bin/start dr-xr-xr-x 1 root root 0 Nov 30 13:56 sys drwxrwxrwt 1 www-data www-data 0 Nov 30 13:56 tmp drwxr-xr-x 2 root root 0 Jan 1 2000 usr drwxr-xr-x 2 root root 0 Nov 28 15:42 var drwxr-xr-x 2 www-data www-data 0 Jan 1 1980 workspace drwxr-xr-x 2 www-data www-data 0 Nov 10 05:57 www-data-home
pwdより先にこっちを実行しとけば良かったですね。/homeや/rootが/tmpにリンクしてるのが面白いところです。
ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND www-data 1 2.0 3.0 644488 63476 ? Ssl 13:10 0:03 node /layers/google.nodejs.functions-framework/functions-framework/node_modules/.bin/functions-framework www-data 15 0.0 0.1 12688 3520 ? S 13:13 0:00 /bin/sh -c ps aux www-data 16 0.0 0.1 42464 3748 ? R 13:13 0:00 ps aux
ナルホドPID:1の /layers/google.nodejs.functions-framework/functions-framework/node_modules/.bin/functions-framework
が関数のプロセスなんですね
uname -a
Linux localhost 4.4.0 #1 SMP Sun Jan 10 15:06:54 PST 2016 x86_64 x86_64 x86_64 GNU/Linux
カーネルは4.4を使っているようです
whoami
www-data
これはHTTPトリガーを指定したからユーザーがwww-data
なのかな?と思い、GCSバケットからトリガーする関数でも試してみましたが、ユーザーは変わらずwww-data
でした
node -v
v14.17.6
2021/11/30時点のNode.jsのランタイムはv14.17.6が動作しているようです
printenv
GCF_BLOCK_RUNTIME_nodejs6=410 S2A_ACCESS_TOKEN=なにかのトークンらしき文字列 NO_UPDATE_NOTIFIER=true K_REVISION=15 SHLVL=1 HOME=/root PORT=8080 NODE_OPTIONS=--max-old-space-size=192 FUNCTION_SIGNATURE_TYPE=http GCF_BLOCK_RUNTIME_go112=410 _=/layers/google.nodejs.functions-framework/functions-framework/node_modules/.bin/functions-framework PATH=/workspace/node_modules/.bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin FUNCTION_TARGET=helloWorld DEBIAN_FRONTEND=noninteractive NODE_PATH=/workspace/node_modules K_SERVICE=os-cmd PWD=/workspace GAE_RUNTIME=nodejs14 NODE_ENV=production
S2A_ACCESS_TOKEN
が何者なのか気になりますね。S2AはSecure Session Agentの略でしょうかね?
https://github.com/google/s2a-core
df -h
Filesystem Size Used Avail Use% Mounted on none 8.0E 0 8.0E 0% /tmp
Availableが8.0E?!こんなの初めて見ました
lscpu
Architecture: x86_64 CPU op-mode(s): 32-bit, 64-bit Byte Order: Little Endian CPU(s): 2 On-line CPU(s) list: 0,1 Vendor ID: GenuineIntel CPU family: 6 Model: 85 Model name: unknown Stepping: unknown CPU MHz: 2679.843 BogoMIPS: 2679.84 Virtualization: VT-x Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm cqm mpx rdt_a avx512f avx512dq rdseed adx smap clwb avx512cd avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves pku
安定のIntel製
lsblk
Error: function terminated. Recommended action: inspect logs for termination reason. Additional troubleshooting documentation can be found at https://cloud.google.com/functions/docs/troubleshooting#logging Details: Command failed: lsblk lsblk: failed to access sysfs directory: /sys/dev/block: No such file or directory
ダメでした!
findmnt
TARGET SOURCE FSTYPE OPTIONS / none overlayfs rw |-/dev none overlayfs rw | `-/dev/shm none tmpfs rw |-/proc none proc rw |-/sys none sysfs rw |-/tmp none tmpfs rw |-/cloudsql none 9p rw `-/var/log none overlayfs rw
注目したいのは/cloudsql none 9p rw
の部分です。9p filesystemなんてのがあるんですね。恥ずかしながら初めて知りました。
dmesg
[ 0.000000] Starting gVisor... [ 0.384209] Letting the watchdogs out... [ 0.720865] Consulting tar man page... [ 0.868943] Checking naughty and nice process list... [ 1.279663] Creating process schedule... [ 1.535912] Daemonizing children... [ 1.683496] Searching for socket adapter... [ 2.025663] Adversarially training Redcode AI... [ 2.468126] Conjuring /dev/null black hole... [ 2.827750] Segmenting fault lines... [ 2.832743] Granting licence to kill(2)... [ 2.939954] Ready!
おお、gVisorの出力が!Cloud FunctionsはgVisor上で動いていると聞いていましたが、こうやってログから確認できるとナルホドとなりますね
まとめ
Cloud Functionsの実行環境について少し詳しくなれました。やはりマネージド・サービスの裏側を想像するのは楽しいですね!
明日12/3は小倉功一 さんです。よろしくお願いします!